module mysock;

import std.socket;
import std.string;
import std.conv;

class MySocket
{
    string LINE_END = "\r\n";
    string res;
    private char[1048576] buf;// 1Mb; always filled from 0 position
    private bool IsChannelAlive = true;
    private Socket sock;
    
    // constructor for socket-client (automatically connects to given point)
    public this(string addr, ushort port)
    {
        sock = new TcpSocket(new InternetAddress(addr, port));
    }
    
    // constructor for socket-server        
    public this(ushort port, string bindAddr = `127.0.0.1`)
    {
        sock = new TcpSocket;
        sock.bind(new InternetAddress(bindAddr, port));
        sock.listen(100);
    }
    
    private this(Socket s)
    {
        sock = s;
    }
    
    public MySocket accept()
    {
        return new MySocket(sock.accept());
    }
    
    public void close()
    {
        sock.shutdown(SocketShutdown.BOTH);
        sock.close();
    }
    
    public bool isAlive()
    {
        return sock.isAlive();
    }
    
    public string remoteAddr()
    {
        return sock.remoteAddress().toString();
    }
    
    public void writeLine(string data)
    {
        sock.send(data ~ LINE_END);
    }
    
    public string readLine()
    {
        if (!IsChannelAlive) return null;
        int NewLineIdx = find(res, LINE_END);
        if (NewLineIdx >= 0) goto ThereIsString;
ReadAgain:
        int Received = sock.receive(buf);
        switch(Received){
        case Socket.ERROR:
            throw new Exception(`Problem reading socket: ` ~ to!(string)(Socket.ERROR));
        case 0:
            IsChannelAlive = false;
            return res;
        default:
            break;
        }
        res ~= buf[0 .. Received];
        NewLineIdx = find(res, LINE_END);
ThereIsString:
        if (NewLineIdx >= 0) {
            auto piece = res[0 .. NewLineIdx].idup;
            res = res[NewLineIdx + LINE_END.length .. $].idup;
            return piece;
        }
        goto ReadAgain;
    }
/+    
    string dump(char[] data, int len)
    {
        char[] b;
        for(int i=0; i < len; i++)
            b ~= ( data[i] > 31 ? data[i] : '.');
        return cast(string)b;
    }
+/
}
